
cd $directory


************************************************
*Set list of margins; becomes points on x axis
************************************************

global MARGLIST = "50 75 100 150 225 330 500 750 1000 1500 2250 3300 5000 7500 10000 15000 22500 33000 50000 75000 100000"
global MARGLISTPCT = ".0000001 .0000002 .0000005 .000001 .000002 .000005 .00001 .00002 .00005 .0001 .0002 .0005 .001"

global LIST = "52201 69001 69101 69006 69106 69201" //M1GerusoEtAl Economist Silver correctedEconomist correctedSilver GSE2010

************************************************
*Storage for Summary Statistics
************************************************

matrix define REC		=J(30, 10, .) 		//table of summary of reversal rates; 						columns are models, rows are critical margins of votes dropped from winner or gained by loser
matrix define RECPCT	=J(30, 10, .) 		//table of summary of reversal rates based on % margins; 	columns are models, rows are %critical margins of votes dropped from winner or gained by loser
matrix define RECDECWIN	=J(30, 10, .) 		//table of summary of reversal rates; condl on D EC WINS
matrix define RECRECWIN	=J(30, 10, .) 		//table of summary of reversal rates; condl on R EC WINS
matrix define RECRECFRACWIN	=J(30, 10, .) 		//table of summary of reversal rates; condl frac of R EC WINS
matrix define RPV		=J(30, 10, .) 		//table of summary of NPV reversal rates;
matrix define RPVPCT	=J(30, 10, .) 		//table of summary of NPV reversal rates; in % margins (pp)

************************************************
*Outer loop - open datasets
************************************************

global LOOP = 2

foreach file in $LIST{

	use "source_data`c(dirsep)'`file'.dta", clear

************************************************
*stats and vars
************************************************

//count states 
local error=0
local counter=1
while `error' != 111 {
	qui cap d total_ev_`counter'
	local error=_rc
	local counter=`counter'+1
}
global STATECOUNT = `counter'-2 
di "$STATECOUNT"
local state_count = `counter'-2 


	//make vars that summarize each election
	qui egen pvotes = rowtotal(twoPartyVotes_*)
	forvalues i = 1(1)`state_count'{
		qui gen rvotes_`i' = twoPartyVotes_`i'* R_pvShare_`i'
	}
	qui egen rvotes = rowtotal(rvotes_*)
	qui gen pvshare = rvotes/pvotes
	qui gen margin_share = abs(0.5-pvshare)*2
	qui gen margin_votes = margin_share*pvotes

	forvalues i = 1(1)`state_count'{
		qui gen rwin_`i' = R_pvShare_`i' > .5
		qui gen rev_`i' = rwin_`i' * total_ev_`i'
	}
	qui egen revn_total= rowtotal(rev_*)
	qui egen ev_denominator = rowtotal(total_ev_*)
	qui gen rwin = revn_total/ev_denominator > 0.5
	qui gen dwin = (ev_denominator-revn_total)/ev_denominator > 0.5
	qui gen cf_revn_total  = revn_total
	qui gen cf_rwin = rwin

	qui gen inv=0
	qui replace inv=1 if  (rwin==1 & pvshare<.5) | (rwin==0 & pvshare>.5)
	
	//This loop identifies which states can flip election on their own (swing==1) and if so, 
	//how many votes must be dropped to do it(vmargin==X)
	forvalues i = 1(1)`state_count'{
		qui gen vmargin_`i' =  twoPartyVotes_`i'*abs(0.5- R_pvShare_`i')*2 //multiply by 2 to get the number of votes that separate candidates ((1-Rshare)-Rshare) = 1-2rshare
		qui replace cf_revn_total = revn_total //reset each loop
		qui replace cf_rwin = rwin //reset each loop
		qui replace cf_revn_total = cf_revn_total - total_ev_`i' if rwin_`i' == 1 //substract state to ECV count if R won the sim (nationally)
		qui replace cf_revn_total = cf_revn_total + total_ev_`i' if rwin_`i' == 0 //add state from ECV count if R lost the sim (nationally)
		qui replace cf_rwin =  cf_revn_total/ev_denominator > 0.5 //did R win in the counterfactual flip of the state?
		qui gen swing_`i' = cf_rwin != rwin //did the outcome of the election change? 
		//^this allows a change from not a tie to a tie or vice versa to count as a change
		qui replace vmargin_`i' = . if swing_`i' == 0 //keep vmargin blank if the state can't flip the election alone
		label var vmargin_`i' "The margin in vote counts in state `i', if `i' could flip EC"
		
		//Levels: cylce through marglist to get probability of flips at each margin
		foreach marg in $MARGLIST{
			qui gen swing`marg'_`i' = swing_`i'==1 & vmargin_`i'<`marg'
			label var swing`marg'_`i' "Binary: is vmargin_`i' less than `marg'"
		}
		//PP: cylce through % marglist to get probability of flips at each margin
		foreach marg in $MARGLISTPCT{
			local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
			qui gen swingpct`labelmarg'_`i' = swing_`i'==1 & (vmargin_`i'/pvote)<`marg'
			label var swingpct`labelmarg'_`i' "Binary: is vmargin_`i' less than `marg' expressed as pct of turnout"
		}	
		
	}
	
	qui gen closest_flippable_state=.
	qui egen min_vmargin = rowmin(vmargin_*) 
	label var min_vmargin "minimum votes needed to flip closest state"
	qui gen tipping_state = .
	forvalues i = 1(1)`state_count'{
		qui replace closest_flippable_state = `i' if min_vmargin == vmargin_`i'
	}
	egen swingers = rowtotal(swing_*)
	
	//Levels EC Reversals 
	foreach marg in $MARGLIST{
		qui egen swing`marg' = rowtotal(swing`marg'_*)
		qui replace swing`marg' = 0 if swing`marg' == .
		*qui gen notReversed`marg' = swing`marg'==0
		*label var notReversed`marg' "EC not reversed by one state dropping `marg' votes"
		qui gen Reversed`marg' = (swing`marg'>0 & swing`marg'<51)
		qui replace Reversed`marg' = 0 if swing`marg' == .
		label var Reversed`marg' "EC reversed by at least one state dropping `marg' votes"
	}
		
	//PP EC Reversals
	foreach marg in $MARGLISTPCT{
		local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
		di `labelmarg'
		qui egen swingpct`labelmarg' = rowtotal(swingpct`labelmarg'_*)
		qui replace swingpct`labelmarg' = 0 if swingpct`labelmarg' == .
		*qui gen notReversed`marg' = swing`marg'==0
		*label var notReversed`marg' "EC not reversed by one state dropping `marg' votes"
		qui gen Reversedpct`labelmarg' = (swingpct`labelmarg'>0 & swingpct`labelmarg'<51)
		qui replace Reversedpct`labelmarg' = 0 if swingpct`labelmarg' == .
		label var Reversedpct`labelmarg' "EC reversed by at least one state dropping `marg' pp votes"
	}
	
	//Levels NPV Reversals
	foreach marg in $MARGLIST{
		qui gen PVswing`marg'=0
		qui replace PVswing`marg' = 1 if margin_votes<`marg'
	}
	//PP NPV Reversals
	foreach marg in $MARGLISTPCT{
		local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
		qui gen PVswingpct`labelmarg'=0
		qui replace PVswingpct`labelmarg' = 1 if (margin_votes/pvotes)<`marg'
	}	

	qui replace swingers = 0 if swingers == .
	qui gen ec_margin = min_vmargin
	qui gen pv_margin = margin_votes
	
	qui gen zero = swingers == 0
	label var swingers "number of states that could swing election"
		
	************************************************
	*Data for  figures
	************************************************
	local col = $LOOP
	di `col'
	di `file'
	matrix REC[1, `col'] 		= `file'
	matrix RECPCT[1, `col'] 	= `file'
	matrix RECDECWIN[1, `col'] 	= `file'
	matrix RECRECWIN[1, `col'] 	= `file'
	matrix RECRECFRACWIN[1, `col'] 	= `file'	
	matrix RPV[1, `col'] 		= `file'
	matrix RPVPCT[1, `col']		= `file'	

	local row = 2 //place marglist in rows starting at 2
	//stores fraction of sims reversed by indicated margin
	foreach marg in $MARGLIST{

		matrix REC[`row',1] = `marg'
		matrix RECDECWIN[`row',1] = `marg'
		matrix RECRECWIN[`row',1] = `marg'
		matrix RECRECFRACWIN[`row',1] = `marg'
		matrix RPV[`row',1] = `marg'
		
		qui summ Reversed`marg'
		matrix REC[`row',`col'] = r(mean)
		
		qui summ Reversed`marg' if dwin==1
		matrix RECDECWIN[`row',`col'] = r(mean)
		qui count if Reversed`marg'==1 & dwin==1	
		local decwin = r(N)
		
		qui summ Reversed`marg' if rwin==1
		matrix RECRECWIN[`row',`col'] = r(mean)
		qui count if Reversed`marg'==1 & rwin==1
		local recwin = r(N)
		
		matrix RECRECFRACWIN[`row',`col']=`recwin'/(`recwin'+`decwin')
		
		qui summ PVswing`marg'
		matrix RPV[`row',`col'] = r(mean)		
		
		local row = `row'+1
	}
	
	local row = 2 //place marglist in rows starting at 2
	//stores fraction of sims reversed by indicated margin
	foreach marg in $MARGLISTPCT{
		local labelmarg = round(1/`marg')  //cant have decimals in localvars used as names
		matrix RECPCT[`row',1] = `marg'
		matrix RPVPCT[`row',1] = `marg'
		
		qui summ Reversedpct`labelmarg'
		matrix RECPCT[`row',`col'] = r(mean)
		qui summ PVswingpct`labelmarg'
		matrix RPVPCT[`row',`col'] = r(mean)		
		
		local row = `row'+1
	}	
	

************************************************
*Outer loop - open datasets
************************************************
	
global LOOP = $LOOP +1		
di "$LOOP"
	
}
global ENDLOOP = $LOOP

cap drop REC*
svmat REC
svmat RECDECWIN
svmat RECRECWIN
svmat RECRECFRACWIN
cap drop RPV*
svmat RPV
cap drop RECPCT*
svmat RECPCT
cap drop RPVPCT*
svmat RPVPCT


************************************************
*Plots
************************************************

qui summ RECPCT2 in 3 
local ecpostY = r(mean) + .0005
qui summ RECPCT1 in 3
local ecpostX = r(mean)

qui summ RPVPCT2 in 14 
local npvpostY = r(mean) - .0127
qui summ RECPCT1 in 14 
local npvpostX = r(mean) - .0005
	
local labsize = "medsmall"
local legsize = "small"
twoway ///
	(connected RECPCT2 RECPCT1 in 2/100 , lw(medium) lcolor(black) ms(none) ) ///
	(connected RECPCT5 RECPCT1 in 6/100 , lw(medium)  lpattern(longdash) lcolor(black) ms(none) ) ///
	(connected RECPCT6 RECPCT1 in 6/100 , lw(medium) lpattern(shortdash) lcolor(black) ms(none) ) ///
	(connected RPVPCT2 RECPCT1 in 2/100 if RPVPCT2>0.00001, lw(medium) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT5 RECPCT1 in 6/100 if RPVPCT5>0.00001, lw(medium) lpattern(longdash) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT6 RECPCT1 in 6/100 if RPVPCT6>0.00001, lw(medium) lpattern(shortdash) lcolor(gs11) ms(none) ) ///
	, ///
	aspect(1) ///
	xtitle("Margin (Percent of Turnout)", size(`labsize')) ///
	ytitle("Probability Margin Is Pivotal", size(`labsize')) ///
	ysc(log r(0.00005 0.25)) ///
	xsc(log r(.00001 .001)) ///
	ylab(0.0001 ".01%" 0.0005 ".05%" 0.0010 ".10%" 0.0050 "0.5%" 0.0100 "1.0%" 0.0500 "5.0%" 0.1000 "10.0%" , nogrid angle(horizontal) labsize(`labsize')) ///
	xlab(.0000001 `"".00001%" "15 votes""' .000001 `"".0001%" "150""'  .00001 `"".001%" "1,500""'  0.0001 `"".01%" "15,000""'  0.001 `"".1%" "150,000""' , nogrid angle(horizontal) labsize(`labsize') ) ///
	graphr(c(white) lc(white)) ///
	name(Modern, replace) ///
	legend(order(2 "Gelman et al., 2020" 1 "Geruso et al., 2022"  3 "Silver, 2020") position(10) col(1) ring(0) region(lwidth(thin)) size(`legsize'))  ///
	text(`ecpostY' `ecpostX' "EC", color(black) size(`labsize')) text(`npvpostY' `npvpostX' "Pop. Vote", color(gs11) size(`labsize'))
	
	graph export "figures`c(dirsep)'Figure2.pdf", replace	
	

	
qui summ RECPCT2 in 3 
local ecpostY = r(mean) + .0005
qui summ RECPCT1 in 3
local ecpostX = r(mean)

qui summ RPVPCT2 in 14 
local npvpostY = r(mean) - .0127
qui summ RECPCT1 in 14
local npvpostX = r(mean) - .0005
	
local labsize = "med"
local legsize = "small"
twoway ///
	(connected RECPCT2 RECPCT1 in 2/100 , lw(medium) lcolor(black) ms(none) ) ///
	(connected RECPCT3 RECPCT1 in 5/100 , lw(thick)  lpattern(..-) lcolor(black) ms(none) ) ///
	(connected RECPCT4 RECPCT1 in 4/100 , lw(thin) lpattern(--.) lcolor(black) ms(none) ) ///
	(connected RECPCT5 RECPCT1 in 5/100 , lw(medium)  lpattern(longdash) lcolor(black) ms(none) ) ///
	(connected RECPCT6 RECPCT1 in 4/100 , lw(medium) lpattern(shortdash) lcolor(black) ms(none) ) ///
	(connected RECPCT7 RECPCT1 in 4/100 , lw(medium) lpattern(dash) lcolor(black) ms(none) ) ///
	(connected RPVPCT2 RECPCT1 in 2/100 if RPVPCT2>0.00001, lw(medium) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT3 RECPCT1 in 2/100 if RPVPCT3>0.00001, lw(thick)  lpattern(..-) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT4 RECPCT1 in 2/100 if RPVPCT4>0.00001, lw(thin) lpattern(--.) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT5 RECPCT1 in 2/100 if RPVPCT5>0.00001, lw(medium)  lpattern(longdash) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT6 RECPCT1 in 2/100 if RPVPCT6>0.00001, lw(medium) lpattern(shortdash) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT7 RECPCT1 in 4/100 if RPVPCT7>0.00001, lw(medium) lpattern(dash) lcolor(gs11) ms(none) ) ///
	, ///
	aspect(1) ///
	xtitle("Margin (Percent of Turnout)", size(`labsize')) ///
	ytitle("Probability Margin Is Pivotal", size(`labsize')) ///
	ysc(log r(0.00005 0.25)) ///
	xsc(log r(.00001 .001)) ///
	ylab(0.0001 ".01%" 0.0005 ".05%" 0.0010 ".10%" 0.0050 "0.5%" 0.0100 "1.0%" 0.0500 "5.0%" 0.1000 "10.0%" , nogrid angle(horizontal) labsize(`labsize')) ///
	xlab(.0000001 `"".00001%" "15""' .000001 `"".0001%" "150""'  .00001 `"".001%" "1,500""'  0.0001 `"".01%" "15,000""'  0.001 `"".1%" "150,000""' , nogrid angle(horizontal) labsize(`labsize') ) ///
	graphr(c(white) lc(white)) ///
	name(Modern_extended_legend, replace) ///
	legend(order(2 "Gelman et al., 2020 (uncorrected)" 4 "Gelman et al., 2020 (corrected)"  3 "Silver, 2020 (uncorrected)" 5 "Silver, 2020 (corrected)" 1 "Geruso et al., 2022" 6 "Gelman, Silver, Edlin, 2012") col(1) size(`legsize'))  ///
	text(`ecpostY' `ecpostX' "EC", color(black)) text(`npvpostY' `npvpostX' "Pop. Vote", color(gs11))
	
	graph export "figures`c(dirsep)'FigureA1a_legend.pdf", replace
	
	
twoway ///
	(connected RECPCT2 RECPCT1 in 2/100 , lw(medium) lcolor(black) ms(none) ) ///
	(connected RECPCT3 RECPCT1 in 5/100 , lw(thick)  lpattern(..-) lcolor(black) ms(none) ) ///
	(connected RECPCT4 RECPCT1 in 4/100 , lw(thin) lpattern(--.) lcolor(black) ms(none) ) ///
	(connected RECPCT5 RECPCT1 in 5/100 , lw(medium)  lpattern(longdash) lcolor(black) ms(none) ) ///
	(connected RECPCT6 RECPCT1 in 4/100 , lw(medium) lpattern(shortdash) lcolor(black) ms(none) ) ///
	(connected RECPCT7 RECPCT1 in 4/100 , lw(medium) lpattern(dash) lcolor(black) ms(none) ) ///
	(connected RPVPCT2 RECPCT1 in 2/100 if RPVPCT2>0.00001, lw(medium) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT3 RECPCT1 in 2/100 if RPVPCT3>0.00001, lw(thick)  lpattern(..-) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT4 RECPCT1 in 2/100 if RPVPCT4>0.00001, lw(thin) lpattern(--.) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT5 RECPCT1 in 2/100 if RPVPCT5>0.00001, lw(medium)  lpattern(longdash) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT6 RECPCT1 in 2/100 if RPVPCT6>0.00001, lw(medium) lpattern(shortdash) lcolor(gs11) ms(none) ) ///
	(connected RPVPCT7 RECPCT1 in 4/100 if RPVPCT7>0.00001, lw(medium) lpattern(dash) lcolor(gs11) ms(none) ) ///
	, ///
	aspect(1) ///
	xtitle("Margin (Percent of Turnout)", size(`labsize')) ///
	ytitle("Probability Margin Is Pivotal", size(`labsize')) ///
	ysc(log r(0.00005 0.25)) ///
	xsc(log r(.00001 .001)) ///
	ylab(0.0001 ".01%" 0.0005 ".05%" 0.0010 ".10%" 0.0050 "0.5%" 0.0100 "1.0%" 0.0500 "5.0%" 0.1000 "10.0%" , nogrid angle(horizontal) labsize(`labsize')) ///
	xlab(.0000001 `"".00001%" "15 votes""' .000001 `"".0001%" "150""'  .00001 `"".001%" "1,500""'  0.0001 `"".01%" "15,000""'  0.001 `"".1%" "150,000""' , nogrid angle(horizontal) labsize(`labsize') ) ///
	graphr(c(white) lc(white)) ///
	name(Modern_extended, replace) ///
	legend(off)  ///
	text(`ecpostY' `ecpostX' "EC", color(black)) text(`npvpostY' `npvpostX' "Pop. Vote", color(gs11))
	
	graph export "figures`c(dirsep)'FigureA1a.pdf", replace

	
************************************************
*Reference Tables
************************************************	
matrix list RECPCT

matrix col1	=RECPCT[2..15,1]
matrix col2 = col1*150000000
matrix col3	=RECPCT[2..15,5]
matrix col4	=RECPCT[2..15,2]
matrix col5	=RECPCT[2..15,6]

//binding low resolution in Silver, Gelman due to truncation of source data
forvalues i=1(1)4{
	matrix col5[`i',1]=.
	matrix col3[`i',1]=.
}
matrix PANELA = (col1,col2,col3,col4,col5)
matrix colnames PANELA = percent votesif150M Gelman Geruso Silver
matrix list PANELA

xml_tab PANELA, save("tables`c(dirsep)'Table2a") replace	
	


